<!-- 
  "author": "Five",
  "license": "Apache-2.0",
  "email": "fivecc@qq.com"
-->
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>蔚蓝|太泗蒂艺术蛋糕</title>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"
    />
    <link type="text/css" rel="stylesheet" href="./css/main.css" />
  </head>
  <body>
    <div id="tagsTitle"></div>
    <div id="Menu">
      <div class="MeunuData" style="background: rgba(255, 255, 255, 0)"></div>
      <a class="github-btn" target="_blank" title="github" href="https://github.com/Five-great/vr-cake-demo">
        <svg
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
          focusable="false"
          viewBox="0 0 24 24"
          class="icon"
          data-v-726b0561=""
        >
          <path
            d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"
          ></path>
        </svg>
      </a>
      <a href="https://gitee.com/fivecc/vr-cake-demo" class="gitee-btn" title="gitee" target="_blank">
      <svg t="1648028102473" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2405" width="24" height="24" data-v-77b6ee9d=""><path d="M512 1024C229.222 1024 0 794.778 0 512S229.222 0 512 0s512 229.222 512 512-229.222 512-512 512z m259.149-568.883h-290.74a25.293 25.293 0 0 0-25.292 25.293l-0.026 63.206c0 13.952 11.315 25.293 25.267 25.293h177.024c13.978 0 25.293 11.315 25.293 25.267v12.646a75.853 75.853 0 0 1-75.853 75.853h-240.23a25.293 25.293 0 0 1-25.267-25.293V417.203a75.853 75.853 0 0 1 75.827-75.853h353.946a25.293 25.293 0 0 0 25.267-25.292l0.077-63.207a25.293 25.293 0 0 0-25.268-25.293H417.152a189.62 189.62 0 0 0-189.62 189.645V771.15c0 13.977 11.316 25.293 25.294 25.293h372.94a170.65 170.65 0 0 0 170.65-170.65V480.384a25.293 25.293 0 0 0-25.293-25.267z" fill="#C71D23" data-v-77b6ee9d=""></path></svg>
      </a>
      <div id="MenuBtn">
        <img src="./img/weilan.jpg" class="showImg" title="蛋糕实物" alt="" />
        <div class="showImgBigBox">
          <img src="./img/weilan.jpg" title="蛋糕实物" alt="" />
        </div>
        <div id="MenuBtnChange">
          <li class="tabel">
            口味:
            <select id="visible">
              <option value="#ffffff" selected="selected">薄荷</option>
              <option value="#d2ffc4">抹茶</option>
            </select>
          </li>
          <li class="tabel">
            尺寸:
            <select id="cokeSize">
              <option value="6" selected="selected">6寸</option>
              <option value="8">8寸</option>
              <option value="86">双层</option>
            </select>
          </li>
          <li class="tabel">
            自旋:<input id="autoRotate" type="checkbox" checked />
          </li>
        </div>
        <div id="MenuBtnClick">
          <li class="btn" id="move">分解</li>
        </div>
      </div>
    </div>

    <div class="show_info animated" style="display: block">
      <div class="info_my">
        <div class="info_mem">
          <div class="nickname" id="dataName"></div>
          <div class="id"></div>
          <div class="vote"></div>
        </div>
      </div>
      <div class="intro" id="dataText"></div>
    </div>

    <div id="container"></div>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
    <script type="module">
      // //three.js webgl - mirror
      import * as THREE from './js/build/three.module.js';
      import { OrbitControls } from './js/controls/OrbitControls.js';
      import { Reflector } from './js/objects/Reflector.js';
      import { EffectComposer } from './js/postprocessing/EffectComposer.js';
      import { RenderPass } from './js/postprocessing/RenderPass.js';
      import { ShaderPass } from './js/postprocessing/ShaderPass.js';
      import { OutlinePass } from './js/postprocessing/OutlinePass.js';
      import { FXAAShader } from './js/shaders/FXAAShader.js';
      // scene size config
      var WIDTH = window.innerWidth;
      var HEIGHT = window.innerHeight;
      // camera config
      var VIEW_ANGLE = 45;
      var ASPECT = WIDTH / HEIGHT;
      var NEAR = 1;
      var FAR = 1500;
      var camera, scene, renderer;
      var cameraControls;
      // outline config
      var composer, effectFXAA, outlinePass;
      var mouse = new THREE.Vector2();
      var selectedObjects = [];
      var raycaster = new THREE.Raycaster();
      var flag = 0;
      var clickedTime = { timeA: ' ', timeB: ' ' };
      var configOutline = {
        //外部轮廓配置
        edgeStrength: 5.0,
        edgeGlow: 1.0,
        edgeThickness: 3.0,
        pulsePeriod: 5,
        visibleEdgeColor: '#efffee',
        hiddenEdgeColor: '#190a05',
        usePatternTexture: false,
      };
      // 常用变量
      var Texture = new THREE.TextureLoader().load(
        './img/weilan_waiquan_bg.png'
      );
      var TextureCute = new THREE.TextureLoader().load(
        './img/weilan_waiquan_qiu.png'
      );
      var group = new THREE.Group(); //
      var groupMain = new THREE.Group();
      groupMain.userData.id = 0;
      var groupMainDabel = new THREE.Group();
      groupMainDabel.userData.id = 1;
      var groupTop = new THREE.Group();
      groupTop.userData.id = 2;
      var hollowCylinder, p2, p3;
      var moveFlag = false; //分解标志
      var removeFlag = 1; //合成标志
      var moveTime = 120; //运动时间
      var moveCount = 0; //运动计数
      var tagsList = []; //标记数组
      var tagsFlag = false;
      var stats = '';
      var colorList = [];
      init(); //初始化
      animate();
      function init() {
        var container = document.getElementById('container');
        // renderer
        renderer = new THREE.WebGLRenderer({ antialias: true });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.shadowMap.enabled = true;
        renderer.setSize(WIDTH, HEIGHT);
        document.body.appendChild(renderer.domElement);
        scene = new THREE.Scene();
        // camera
        camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
        camera.position.set(-160, 165, -280);
        cameraControls = new OrbitControls(camera, renderer.domElement);
        cameraControls.target.set(0, 75, 0);
        cameraControls.maxDistance = 600;
        cameraControls.minDistance = 10;
        cameraControls.autoRotate = true;
        cameraControls.autoRotateSpeed = 0.8; //自动旋转速度，正比
        var planeGeo = new THREE.PlaneBufferGeometry(1500.1, 1500.1);
        var planeBottom = new THREE.Mesh(
          planeGeo,
          new THREE.MeshPhongMaterial({ color: 0xffffff })
        );
        planeBottom.rotateX(-Math.PI / 2);
        planeBottom.position.y = -10;
        scene.add(planeBottom);
        scene.add(group);
        group.add(groupMain);
        groupMainDabel.visible = false;
        groupMainDabel.scale.set(1.33, 1.33, 1.33);
        group.add(groupMainDabel);
        groupTop.position.set(0, 26, 0);
        group.add(groupTop);
        staticModelFun();
        lightsFun(); //灯光
        mainModel(); //主要模型
        mainModel(); //主要模型
        mainModel(); //主要模型
        topModel(); //顶部模型
        topModel(); //顶部模型
        topModel(); //顶部模型
        outlinePassFun(); //外轮廓
        window.addEventListener('resize', onWindowResize, false);
        window.addEventListener('mousemove', onTouchMove);
        window.addEventListener('touchmove', onTouchMove, true);
        window.addEventListener('click', dbClick, true);
        function onWindowResize() {
          var width = window.innerWidth;
          var height = window.innerHeight;
          camera.aspect = width / height;
          camera.updateProjectionMatrix();
          renderer.setSize(width, height);
          composer.setSize(width, height);
          effectFXAA.uniforms['resolution'].value.set(
            1 / window.innerWidth,
            1 / window.innerHeight
          );
        }
        function onTouchMove(event) {
          event.preventDefault();
          var x, y;
          if (event.changedTouches) {
            x = event.changedTouches[0].pageX;
            y = event.changedTouches[0].pageY;
          } else {
            x = event.clientX;
            y = event.clientY;
          }
          mouse.x = (x / window.innerWidth) * 2 - 1;
          mouse.y = -(y / window.innerHeight) * 2 + 1;
          checkIntersection();
        }
        function dbClick(event) {
          if (flag == 1) {
            clickedTime.timeB = new Date().getTime();
            if (Math.abs(clickedTime.timeB - clickedTime.timeA) < 500) {
              console.log('双击');
              onTouchMove(event);
            }
            flag = 0;
          } else {
            flag++;
            clickedTime.timeA = new Date().getTime();
          }
        }

        function checkIntersection() {
          raycaster.setFromCamera(mouse, camera);
          var intersects = raycaster.intersectObjects([scene], true);
          if (intersects.length > 0) {
            var selectedObject = intersects[0].object;
            addSelectedObject(selectedObject);
            outlinePass.selectedObjects = selectedObjects;
          } else {
          }
        }

        //获取同层次同组模型
        function getType1(object) {
          var objs = [];
          if (object.userData.id == object.parent.userData.id)
            object.parent.parent.children.forEach((ele) => {
              ele.userData.id == object.userData.id
                ? objs.push(ele.children[0])
                : 0;
            });
          //特殊 嵌套组
          else
            object.parent.children.forEach((ele) => {
              ele.userData.id == object.userData.id ? objs.push(ele) : 0;
            });
          return objs;
        }

        //获取不同层次组模型
        function getTypes(object) {
          var parentsId = []; // 记录层
          var rootObj = object; //根
          var arr = [new Array(), new Array()]; // 广搜数组
          var cout = 0; // 广搜滚动 参数
          var objs = [];
          for (var i = 1; i <= object.userData.type; i++) {
            rootObj = rootObj.parent;
            parentsId.push({ pid: rootObj.userData.id });
          } //找到 root
          arr[cout].push(rootObj); //加入 root
          parentsId.pop(); //抛掉 root 的Id
          while (parentsId.length > 0) {
            arr[cout].pop().children.forEach((ele) => {
              ele.userData.id == parentsId[parentsId.length - 1].pid
                ? arr[(cout + 1) % 2].push(ele)
                : 0;
            });
            if (arr[cout].length == 0) {
              cout = (cout + 1) % 2;
              parentsId.pop();
            } //抛掉已查找的pid
          }
          //找到同层次同组
          for (var i = 0; i < arr[cout].length; i++)
            arr[cout][i].children.forEach((ele) => {
              ele.userData.id == object.userData.id ? objs.push(ele) : 0;
            });

          return objs;
        }

        function addSelectedObject(object) {
          selectedObjects = [];
          if (object.name) {
            $('#dataText')[0].innerText = object.userData.text;
            $('#dataName')[0].innerText = object.name;
            $('.show_info').addClass('on');
            if (object.userData.type == 0) selectedObjects.push(object);
            if (object.userData.type == 1) selectedObjects = getType1(object);
            if (object.userData.type == 2) selectedObjects = getTypes(object);
          } else $('.show_info').removeClass('on');
        }
      }

      function topModel() {
        var glass_material = new THREE.MeshBasicMaterial({ color: 0x62cadd });
        glass_material.opacity = 0.65;
        glass_material.transparent = true;
        var geometry = new THREE.CylinderBufferGeometry(39, 39, 2, 128);
        var P2 = new THREE.Mesh(geometry, glass_material);
        P2.opacity = 0.5;
        P2.receiveShadow = true;
        P2.name = '蓝色的海(果冻)';
        P2.userData = { type: 0, id: 16, sO: 2, sV: 18, sI: 100 };
        P2.userData.text = '主要成分：果冻 ';
        groupTop.add(P2);
        var geometry = new THREE.SphereBufferGeometry(
          5,
          24,
          24,
          Math.PI / 2,
          Math.PI * 2,
          0,
          (Math.PI / 180) * 60
        );
        var material = new THREE.MeshBasicMaterial({ color: 0x000000 });
        material.side = THREE.DoubleSide; //两面都显示
        var P111 = new THREE.Mesh(geometry, material);
        P111.position.y = 8.9;
        P111.scale.set(2, 1.6, 1.52);
        P111.rotateX(Math.PI + 0.05);
        P111.rotateY(Math.PI);
        P111.name = '帆船(饰品)';
        P111.userData = { type: 0, id: 18, sO: 2, sV: 25, sI: 100 };
        P111.userData.text = '主要成分巧克力 ';
        groupTop.add(P111);

        var P1 = new THREE.Mesh(
          new THREE.SphereBufferGeometry(0.1, 0.1, 24),
          material
        );
        P1.position.y = 7.3;
        P1.rotateX(Math.PI - 0.05);
        P111.add(P1);

        var glass_material = new THREE.MeshBasicMaterial({ color: 0xfedd91 });
        glass_material.opacity = 0.95;
        glass_material.transparent = true;
        var geometry = new THREE.CylinderBufferGeometry(3, 3, 0.2, 64);
        var cube = new THREE.Mesh(geometry, glass_material);
        cube.position.set(0, 3.1, 0);
        cube.rotation.x = Math.PI - 0.15;
        cube.scale.set(1.1, 0.9, 0.98);
        cube.opacity = 0.5;
        cube.receiveShadow = true;
        P111.add(cube);
        //船桨
        var x = 3,
          y = 30,
          z = 0.3;
        var geometry = new THREE.BoxGeometry(x, y, z);
        geometry.vertices[4].x += x - 0.1;
        geometry.vertices[5].x += x - 0.1;
        var material = new THREE.MeshBasicMaterial({ color: 0x000000 });
        var mash = new THREE.Mesh(geometry, material);
        mash.position.set(0, 3.2, 6);
        mash.rotateX(-Math.PI * 0.5 - 0.1);
        mash.rotateY(Math.PI * 0.3);
        mash.scale.set(0.3, 0.3, 0.3);
        P111.add(mash);
        var mash = new THREE.Mesh(geometry, material);
        mash.position.set(1, 3.3, -6);
        mash.rotateX(Math.PI * 0.5 + 0.5);
        mash.rotateY(-Math.PI * 0.2);
        mash.scale.set(0.3, 0.3, 0.3);
        P111.add(mash);
        //船帆
        var x = 9,
          y = 17,
          z = 0.3;
        var geometry = new THREE.BoxGeometry(x, y, z);
        geometry.vertices[4].x += x - 0.1;
        geometry.vertices[5].x += x - 0.1;
        var mash = new THREE.Mesh(
          geometry,
          new THREE.MeshBasicMaterial({ map: TextureCute })
        );
        mash.position.set(-1, -2, 0);
        mash.rotateX(-Math.PI);
        mash.rotateZ(Math.PI * 0.15);
        mash.scale.set(0.6, 0.6, 0.6);
        P111.add(mash);
        P1.scale.set(1.3, 1.3, 1.3);
      }

      function mainModel() {
        //模型
        var P = new THREE.Mesh(
          new THREE.CylinderBufferGeometry(40, 40, 10, 64),
          new THREE.MeshBasicMaterial({ color: 0xfedd91 })
        );
        P.name = '蛋糕胚子(底部)';
        P.position.set(0, 0, 0);
        groupMain.add(P);
        P.userData = { type: 0, id: 11 };
        P.userData.text = '主要成分：蛋糕';
        groupMainDabel.add(P.clone());
        P = new THREE.Mesh(
          new THREE.CylinderBufferGeometry(40, 40, 10, 64),
          new THREE.MeshBasicMaterial({ color: 0xfedd91 })
        );

        P.name = '蛋糕胚子(中部)';
        P.position.set(0, 12, 0);
        groupMain.add(P);
        P.userData = { type: 0, id: 12, sO: 2, sV: 8, sI: 100, sC: 0 };
        P.userData.text = '主要成分：蛋糕';
        groupMainDabel.add(P.clone());
        P = new THREE.Mesh(
          new THREE.CylinderBufferGeometry(42, 42, 4, 64),
          new THREE.MeshBasicMaterial({ map: Texture })
        );
        P.name = '慕斯夹层(中部)';
        P.position.set(0, 5, 0);
        groupMain.add(P);
        P.userData = { type: 0, id: 13, sO: 2, sV: 5, sI: 100, sC: 0 };
        P.userData.text = '主要成分：慕斯';
        colorList.push(P);
        groupMainDabel.add(P.clone());
        P = new THREE.Mesh(
          new THREE.CylinderBufferGeometry(41, 41, 6, 64),
          new THREE.MeshBasicMaterial({ map: Texture })
        );
        P.name = '慕斯夹层(顶部)';
        P.position.set(0, 21, 0);
        groupMain.add(P);
        P.userData = { type: 0, id: 14, sO: 2, sV: 10, sI: 100, sC: 0 };
        P.userData.text = '主要成分：慕斯';
        colorList.push(P);
        groupMainDabel.add(P.clone());
        // type:  0 ==> 单模型 只有该模型   1==> 模型组 同组同层次多个模型  2 ==> 不同组同层次模型组(最近根组向上2层), 复数 指定同组同层次索引
        //  id  ==> 2 同模型组  id 相同  id   2 位数运动 ，3位数 随动
        //sO ==>运动方向类型参数，(1, 2, 4 ,-1,-2,-4   4 ==> 100 二进制标识  x==>100 y==>010 z==>001  -4 代表 -x 方向)
        //sV ==> 运动速度 1~100 速度正比
        //sI ==> 运动增量 最终增加的大小
        //sC ==> 运动变化存储（中间变量）
        var groupHollowCylinder = new THREE.Group();
        groupHollowCylinder.userData = {
          type: 1,
          id: 10,
          sO: 4,
          sV: 50,
          sI: 100,
          sC: 0,
        };
        groupMain.add(groupHollowCylinder);
        groupHollowCylinder.position.set(0, 11, 0);
        var geometry = new THREE.HollowCylinder(
          51,
          51,
          10,
          28,
          64,
          32,
          false,
          0,
          Math.PI
        );
        var material = new THREE.MeshBasicMaterial({ map: Texture });
        material.side = THREE.DoubleSide; //两面都显示
        hollowCylinder = new THREE.Mesh(geometry, material);
        hollowCylinder.name = '慕斯外边';
        hollowCylinder.userData = { type: 1, id: 10 };
        hollowCylinder.userData.text = '主要成分：慕斯粉';
        groupHollowCylinder.add(hollowCylinder);
        var ge = new THREE.SphereBufferGeometry(3, 64, 64);
        var ma = new THREE.MeshBasicMaterial({ color: 0x7e8c19 });
        var cube = new THREE.Mesh(ge, ma);
        cube.position.set(49 * Math.sin(0.3), 4.4, 49 * Math.cos(0.3));
        cube.name = '巧克力青色';
        cube.userData = { type: 2, id: 101 };
        cube.userData.text = '为巧克力制作而成 外部点缀';
        groupHollowCylinder.add(cube);
        var cube2 = cube.clone();
        cube2.position.set(51 * Math.sin(1), -3, 51 * Math.cos(1));
        groupHollowCylinder.add(cube2);
        cube2 = cube.clone();
        cube2.position.set(50 * Math.sin(1.8), 9, 50 * Math.cos(1.8));
        groupHollowCylinder.add(cube2);
        cube2 = cube.clone();
        cube2.position.set(51.5 * Math.sin(2.8), -9, 51.5 * Math.cos(2.8));
        groupHollowCylinder.add(cube2);

        groupMainDabel.add(groupHollowCylinder.clone());

        var groupHollowCylinder2 = groupHollowCylinder.clone();
        groupHollowCylinder2.userData.sO = -4;
        groupHollowCylinder2.rotateY(Math.PI);
        groupMain.add(groupHollowCylinder2);
        colorList.push(groupHollowCylinder2.children[0]);
        groupMainDabel.add(groupHollowCylinder2.clone());
        var str = '';
        cube.userData.tagData = {
          x: 52 * Math.sin(0.3),
          y: 4.4,
          z: 52 * Math.cos(0.3),
          aX: 0,
          aY: 20,
          aZ: 15,
        };
        cube.add(
          draw_line(
            { x: 0, y: 0, z: 4, aX: 0, aY: 20, aZ: 15 },
            0,
            Math.PI * 0.1,
            0
          )
        ); //加入line
        str += '<div id="' + cube.userData.id + '">' + cube.name + '</div>\n';
        tagsList.push(cube); //加入标签数组
        hollowCylinder.userData.tagData = {
          x: 52.5,
          y: 0,
          z: 0,
          aX: 10,
          aY: 45,
          aZ: 0,
        };
        hollowCylinder.add(
          draw_line(hollowCylinder.userData.tagData, 0, Math.PI * 0.5, 0)
        ); //加入line
        str +=
          '<div id="' +
          hollowCylinder.userData.id +
          '">' +
          hollowCylinder.name +
          '</div>\n';
        tagsList.push(hollowCylinder); //加入标签数组
        colorList.push(hollowCylinder);
        $('#tagsTitle').html(str);
      }

      //划线
      function draw_line(d, rX, rY, rZ) {
        var material = new THREE.LineBasicMaterial({ color: 0x0077ff });
        var geometry = new THREE.Geometry();
        geometry.vertices.push(new THREE.Vector3(d.x, d.y, d.z));
        geometry.vertices.push(
          new THREE.Vector3(d.x + d.aX, d.y + d.aY, d.z + d.aZ)
        );
        var line = new THREE.Line(geometry, material);
        var circle2 = new THREE.Mesh(
          new THREE.CircleGeometry(2, 32),
          new THREE.MeshBasicMaterial({
            color: 0x0082ff,
            side: THREE.DoubleSide,
            opacity: 0.65,
          })
        );
        var circle1 = new THREE.Mesh(
          new THREE.CircleGeometry(2.8, 32),
          new THREE.MeshBasicMaterial({
            color: 0x0ea7ff,
            side: THREE.DoubleSide,
            opacity: 0.5,
          })
        );
        var circle = new THREE.Mesh(
          new THREE.CircleGeometry(3.5, 32),
          new THREE.MeshBasicMaterial({
            color: 0x0aaeff,
            side: THREE.DoubleSide,
            opacity: 0.4,
            transparent: true,
          })
        );
        var circle22 = new THREE.Mesh(
          new THREE.CircleGeometry(2, 32),
          new THREE.MeshBasicMaterial({
            color: 0x0082ff,
            side: THREE.DoubleSide,
            opacity: 0.65,
          })
        );
        circle.add(circle1);
        circle2.position.set(0, 0.1, 0.1);
        circle.add(circle2);
        circle22.position.set(0, -0.05, -0.5);
        circle.add(circle22);
        circle.position.set(d.x, d.y, d.z);
        circle.rotation.set(rX, rY, rZ);
        line.add(circle);
        line.visible = false;
        return line;
      }

      //基模型
      function staticModelFun() {
        // 消除heover
        var staticModel = new THREE.Mesh(
          new THREE.BoxGeometry(0.5, 0.5, 0.2),
          new THREE.MeshBasicMaterial({ color: 0x7c7c7c })
        );
        staticModel.position.y = -10;
        staticModel.opacity = 0.0;
        group.add(staticModel);
        // reflectors/mirrors
        var geometry = new THREE.CircleBufferGeometry(140, 64);
        var groundMirror = new Reflector(geometry, {
          clipBias: 0.003,
          textureWidth: WIDTH * window.devicePixelRatio,
          textureHeight: HEIGHT * window.devicePixelRatio,
          color: 0x777777,
          recursion: 1,
        });
        groundMirror.position.y = 3;
        groundMirror.rotateX(-Math.PI / 2);
        staticModel.add(groundMirror);
        //茶色：0x58ACFA 透明玻璃色：0XECF1F3
        var glass_material = new THREE.MeshBasicMaterial({ color: 0x7c7c7c });
        glass_material.opacity = 0.45;
        glass_material.transparent = true;
        var cube = new THREE.Mesh(
          new THREE.BoxGeometry(155, 155, 2.2),
          glass_material
        );
        cube.position.set(0, 4, 0);
        cube.rotation.x = -Math.PI * 0.5;
        cube.opacity = 0.1;
        cube.receiveShadow = true;
        staticModel.add(cube);
      }

      // 外部轮廓
      function outlinePassFun() {
        composer = new EffectComposer(renderer);
        var renderPass = new RenderPass(scene, camera);
        composer.addPass(renderPass);
        outlinePass = new OutlinePass(
          new THREE.Vector2(window.innerWidth, window.innerHeight),
          scene,
          camera
        );
        outlinePass.edgeStrength = configOutline.edgeStrength;
        outlinePass.edgeGlow = configOutline.edgeGlow;
        outlinePass.edgeThickness = configOutline.edgeThickness;
        outlinePass.pulsePeriod = configOutline.pulsePeriod;
        outlinePass.usePatternTexture = configOutline.usePatternTexture;
        outlinePass.visibleEdgeColor.set(configOutline.visibleEdgeColor);
        outlinePass.hiddenEdgeColor.set(configOutline.hiddenEdgeColor);
        composer.addPass(outlinePass);
        effectFXAA = new ShaderPass(FXAAShader);
        effectFXAA.uniforms['resolution'].value.set(
          1 / window.innerWidth,
          1 / window.innerHeight
        );
        composer.addPass(effectFXAA);
      }

      // 灯光
      function lightsFun() {
        var mainLight = new THREE.PointLight(0xcccccc, 1.5, 350);
        mainLight.position.y = 80;
        scene.add(mainLight);
        var greenLight = new THREE.PointLight(0x00ff00, 0.25, 1000);
        greenLight.position.set(550, 70, 0);
        scene.add(greenLight);
        var redLight = new THREE.PointLight(0xff0000, 0.25, 1000);
        redLight.position.set(-550, 70, 0);
        scene.add(redLight);
        var blueLight = new THREE.PointLight(0x7f7fff, 0.25, 1000);
        blueLight.position.set(0, 70, 550);
        scene.add(blueLight);
      }

      function modelMove() {
        moveCount++;
        groupMain.children.forEach((ele) => {
          if (ele.userData.id <= 99) {
            Math.abs(ele.userData.sO) & 4
              ? (ele.position.x +=
                  ((removeFlag * ele.userData.sO) / Math.abs(ele.userData.sO)) *
                  ele.userData.sV *
                  0.01)
              : 0;
            Math.abs(ele.userData.sO) & 2
              ? (ele.position.y +=
                  ((removeFlag * ele.userData.sO) / Math.abs(ele.userData.sO)) *
                  ele.userData.sV *
                  0.01)
              : 0;
            Math.abs(ele.userData.sO) & 1
              ? (ele.position.z +=
                  ((removeFlag * ele.userData.sO) / Math.abs(ele.userData.sO)) *
                  ele.userData.sV *
                  0.01)
              : 0;
          }
        });
        groupTop.children.forEach((ele) => {
          if (ele.userData.id <= 99) {
            Math.abs(ele.userData.sO) & 4
              ? (ele.position.x +=
                  ((removeFlag * ele.userData.sO) / Math.abs(ele.userData.sO)) *
                  ele.userData.sV *
                  0.01)
              : 0;
            Math.abs(ele.userData.sO) & 2
              ? (ele.position.y +=
                  ((removeFlag * ele.userData.sO) / Math.abs(ele.userData.sO)) *
                  ele.userData.sV *
                  0.01)
              : 0;
            Math.abs(ele.userData.sO) & 1
              ? (ele.position.z +=
                  ((removeFlag * ele.userData.sO) / Math.abs(ele.userData.sO)) *
                  ele.userData.sV *
                  0.01)
              : 0;
          }
        });
        if (moveCount >= moveTime) {
          moveCount = 0;
          moveFlag = false;
          if (removeFlag == 1) {
            $('#move')[0].innerHTML = '合成';
            tagsFlag = true;
            $('#tagsTitle').addClass('on');
            tagsVisbleFun(true);
            removeFlag = -1;
          } else {
            $('#move')[0].innerHTML = '分解';
            removeFlag = 1;
            tagsFlag = false;
            $('#tagsTitle').removeClass('on');
            tagsVisbleFun(false);
          }
        }
      }

      function tagsTitleFun() {
        let halfWidth = window.innerWidth / 2;
        let halfHeight = window.innerHeight / 2;
        let vector1;
        tagsList.forEach((ele) => {
          let ppPosition = ele.parent.parent.position;
          let ppScale = ele.parent.parent.scale;
          vector1 = getVector(
            ele.parent.position,
            {
              x: ppPosition.x + ele.userData.tagData.x,
              y: ppPosition.y + ele.userData.tagData.y,
              z: ppPosition.z + ele.userData.tagData.z,
              aX: ele.userData.tagData.aX,
              aY: ele.userData.tagData.aY,
              aZ: ele.userData.tagData.aZ,
            },
            ppScale
          ).project(camera);
          $('#' + ele.userData.id).css({
            left: vector1.x * halfWidth - 15 + halfWidth,
            top: -vector1.y * halfHeight - 10 + halfHeight,
          });
        });
      }

      function tagsVisbleFun(V) {
        tagsList.forEach((ele) => {
          ele.children[ele.children.length - 1].visible = V;
        });
      }

      function getVector(v1, v2, ppScale) {
        return new THREE.Vector3(
          ppScale.x * (v1.x + v2.x + v2.aX),
          ppScale.y * (v1.y + v2.y + v2.aY),
          ppScale.z * (v1.z + v2.z + v2.aZ)
        );
      }

      function animate() {
        requestAnimationFrame(animate);
        var timer = Date.now() * 0.01;
        moveFlag ? modelMove() : 0;
        tagsFlag ? tagsTitleFun() : 0;
        cameraControls.update();
        composer.render();
      }

      $('#MenuBtnClick').on('click', function (e) {
        var target = e.target || e.srcElement;
        if (target.id == 'move') {
          moveFlag ? (moveFlag = false) : (moveFlag = true);
          target.innerHTML == '暂停'
            ? (target.innerHTML = '继续')
            : (target.innerHTML = '暂停');
        }
      });

      $('#MenuBtnChange').on('change', function (e) {
        var target = e.target || e.srcElement;
        if (target.id == 'autoRotate') {
          cameraControls.autoRotate
            ? (cameraControls.autoRotate = false)
            : (cameraControls.autoRotate = true);
        }
        if (target.id == 'visible')
          colorList.forEach((ele) => {
            ele.material.color.set(target.value);
          });
        if (target.id == 'cokeSize') {
          if (target.value == '6') {
            groupMain.scale.set(1, 1, 1);
            groupTop.position.y = 26;
            if (groupMainDabel.visible) {
              groupMain.position.y -= 36;
              groupMainDabel.visible = false;
            }
          }
          if (target.value == '8') {
            groupMain.scale.set(1.33, 1.33, 1.33);
            groupTop.position.y = 33;
            if (groupMainDabel.visible) {
              groupMain.position.y -= 36;
              groupMainDabel.visible = false;
            }
          }
          if (target.value == '86') {
            groupTop.position.y = 62;
            if (!groupMainDabel.visible) {
              groupMain.position.y += 36;
              groupMain.scale.set(1, 1, 1);
              groupMainDabel.visible = true;
            }
          }
        }
      });
    </script>
  </body>
</html>
